#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NorthEastWay EA代码重命名脚本 - 修复版
将反编译的变量名和函数名替换为有意义的名称
"""

import re
import os
import sys
import codecs

def detect_encoding(file_path):
    """检测文件编码"""
    # 尝试不同的编码
    encodings = ['utf-8', 'utf-8-sig', 'gbk', 'gb2312', 'gb18030', 'latin-1', 'utf-16', 'utf-16-le', 'utf-16-be']
    
    for encoding in encodings:
        try:
            with codecs.open(file_path, 'r', encoding=encoding) as f:
                content = f.read(1000)  # 读取前1000个字符测试
                # 检查是否包含MQL代码的特征
                if '#property' in content or 'extern' in content or 'int OnInit' in content:
                    print(f"检测到文件编码: {encoding}")
                    return encoding
        except:
            continue
    
    return None

def apply_renames():
    # 源文件和输出文件
    source_file = "东北路源码North East Way .mq4"
    output_file = "NorthEastWay_Readable_Fixed.mq4"
    
    # 检查源文件是否存在
    if not os.path.exists(source_file):
        print(f"错误: 找不到源文件 {source_file}")
        return
    
    # 检测文件编码
    encoding = detect_encoding(source_file)
    if encoding is None:
        print("无法检测文件编码，使用默认编码")
        encoding = 'utf-8'
    
    # 读取源文件内容
    try:
        with codecs.open(source_file, 'r', encoding=encoding) as f:
            content = f.read()
        print(f"成功使用编码 {encoding} 读取文件")
    except Exception as e:
        print(f"读取文件失败: {e}")
        return
    
    # 定义重命名映射
    rename_map = {
        # 函数重命名
        r'\blizong_12\b': 'GetAccountStatus',
        r'\blizong_13\b': 'ResetGlobalVariables',
        r'\blizong_14\b': 'ModifyOrder',
        r'\blizong_15\b': 'OpenPosition',
        r'\blizong_16\b': 'CalculateLotSize',
        r'\blizong_17\b': 'CloseOrdersByType',
        r'\blizong_18\b': 'GetErrorDescription',
        r'\blizong_19\b': 'ManageAddPosition',
        r'\blizong_20\b': 'CurrencyToIndex',
        r'\blizong_21\b': 'GetOrdersProfit',
        r'\blizong_22\b': 'GetOrdersCount',
        r'\blizong_23\b': 'ParseSettingsString',
        r'\blizong_24\b': 'InitializeArrays',
        r'\blizong_25\b': 'CreateGraphicObject',
        r'\blizong_26\b': 'CreateDashboardPanel',
        r'\blizong_27\b': 'UpdateDashboardInfo',
        r'\blizong_28\b': 'GetTradingModeText',
        r'\blizong_29\b': 'EmergencyHandler',
        r'\blizong_30\b': 'CloseAllPositions',
        
        # 辅助函数重命名
        r'\babc\b': 'TrimString',
        r'\bxx\(': 'SplitString(',
        r'\bxx1\b': 'ParseSymbolMultipliers',
        r'\bxx3\b': 'CopySettingsArray',
        r'\byy\b': 'CopySettingsStruct',
        r'\brrr\b': 'InitializeTerminal',
        r'\bzs1\b': 'GetSymbolPrefix',
        r'\bzs2\b': 'GetMagicSuffix',
        
        r'\blizongs1\b': 'HasOpenOrders',
        r'\blizongs2\b': 'CheckOrderExists',
        r'\blizongs3\b': 'GetOrderComment',
        r'\blizongs4\b': 'SetVirtualTakeProfit',
        r'\blizongs5\b': 'CheckHolidayRestriction',
        r'\blizongs6int\b': 'CountOtherMagics',
        r'\blizongs6str\b': 'CountOtherSymbols',
        r'\blizongs7\b': 'UpdateGridDistance',
        r'\blizongs8\b': 'CalculateBreakeven',
        r'\blizongs9\b': 'CheckDrawdownLimit',
        r'\blizongs10\b': 'IsFirstPositionAllowed',
        r'\blizongs11\b': 'GetMaxOrderLevel',
    }
    
    # 全局变量重命名映射（前100个）
    global_renames = {
        'global_1_st': 'g_EAVersion',
        'global_2_a_160_ko': 'g_SettingsArray',
        'global_3_in': 'g_SettingsMode',
        'global_4_st': 'g_CustomSettings',
        'global_5_in': 'g_MaxAdvisors',
        'global_6_bo': 'g_ShowDashboard',
        'global_7_in': 'g_TerminalType',
        'global_8_in': 'g_TotalAdvisors',
        'global_9_in': 'g_MagicConstant1',
        'global_10_in': 'g_MagicConstant2',
        'global_11_in': 'g_MagicConstant3',
        'global_12_sh': 'g_MagicConstant4',
        'global_13_st': 'g_ExecutionLabel',
        'global_14_in': 'g_CurrentLevel',
        'global_15_in': 'g_MaxSlippage',
        'global_16_bo': 'g_UseECNMode',
        'global_17_do': 'g_MaxSpread',
        'global_18_in': 'g_MaxRetries',
        'global_19_in': 'g_MinPipStep',
        'global_20_in': 'g_MaxPipStep',
        'global_21_do': 'g_LotMultiplier',
        'global_22_in': 'g_GridLevels',
        'global_23_do': 'g_MinProfitPercent',
        'global_24_bo': 'g_UseGridTrading',
        'global_25_in': 'g_CurrentMagic',
        'global_26_in': 'g_InternalMagic',
        'global_27_in': 'g_SetIndex',
        'global_28_do': 'g_TakeProfit1',
        'global_29_do': 'g_TakeProfit2',
        'global_30_in': 'g_TakeProfitPips',
        'global_31_do': 'g_StopLossMultiplier',
        'global_32_do': 'g_DrawdownPercent',
        'global_33_do': 'g_Reserved1',
        'global_34_do': 'g_AutoMMFactor',
        'global_35_do': 'g_MinLotMultiplier',
        'global_36_do': 'g_DefaultLotSize',
        'global_37_do': 'g_MaxLotSize',
        'global_38_st': 'g_LotLimitLabel',
        'global_39_bo': 'g_UseLotLimit',
        'global_40_do': 'g_MaxLotPerTrade',
        'global_41_bo': 'g_UseDrawdownControl',
        'global_42_do': 'g_MartinMultiplier',
        'global_43_in': 'g_RecoveryProfitPercent',
        'global_44_in': 'g_RecoveryLossPercent',
        'global_45_in': 'g_MaxRecoveryLevel',
        'global_46_st': 'g_TesterLabel',
        'global_47_bo': 'g_TesterOption1',
        'global_48_bo': 'g_TesterOption2',
        'global_49_bo': 'g_TesterOption3',
        'global_50_st': 'g_CurrentSymbol',
        'global_51_in': 'g_SymbolDigits',
        'global_52_in': 'g_LastBarTime',
        'global_53_do': 'g_AccountBalance',
        'global_54_in': 'g_TotalOrders',
        'global_55_do': 'g_MinPrice',
        'global_56_do': 'g_MaxPrice',
        'global_57_do': 'g_AveragePrice',
        'global_58_do': 'g_TotalLots',
        'global_59_in': 'g_BuyOrders',
        'global_60_in': 'g_SellOrders',
        'global_61_in': 'g_LastOrderType',
        'global_62_in': 'g_OrdersArrayIndex',
        'global_63_in': 'g_MaxOrdersInArray',
        'global_64_in': 'g_PendingBuyOrders',
        'global_65_in': 'g_PendingBuyLimitOrders',
        'global_66_in': 'g_PendingSellOrders',
        'global_67_in': 'g_PendingSellLimitOrders',
        'global_68_in': 'g_LastProcessedBar',
        'global_69_do': 'g_NextEntryPrice',
        'global_70_in': 'g_GridDistancePoints',
        'global_71_in': 'g_AccountStatus',
        'global_72_in': 'g_LastEquity',
        'global_73_in': 'g_ConsecutiveLosses',
        'global_74_in': 'g_ConsecutiveWins',
        'global_75_in': 'g_LastTicket',
        'global_76_in': 'g_ErrorCount',
        'global_77_bo': 'g_IsTradeAllowed',
        'global_78_in_si100si15': 'g_OrdersHistory',
        'global_79_in': 'g_HistoryIndex',
        'global_80_in': 'g_LastUpdateTime',
        'global_81_in': 'g_ChartWindowIndex',
        'global_82_in': 'g_DashboardX',
        'global_83_in': 'g_DashboardY',
        'global_84_in': 'g_DashboardWidth',
        'global_85_do_si7si10000': 'g_OrderProfitArray',
        'global_86_st_si40000': 'g_OrderCommentArray',
        'global_87_in_si40000': 'g_OrderTicketArray',
        'global_88_in': 'g_OrdersCount',
        'global_89_in': 'g_LastProcessedOrder',
        'global_90_in': 'g_TotalProcessedOrders',
        'global_91_do': 'g_TotalProfit',
        'global_92_do': 'g_MaxDrawdown',
        'global_93_st': 'g_AdvisorIndex',
        'global_94_in': 'g_LoopCounter',
        'global_95_in': 'g_TimerCounter',
        'global_96_in': 'g_LastCalculationTime',
        'global_97_in': 'g_InitializationStatus',
        'global_98_in': 'g_TotalSymbols',
        'global_99_st_si1': 'g_SymbolsArray',
        'global_100_do_si1': 'g_SymbolMultiplierArray',
    }
    
    # 添加更多全局变量（101-131）
    for i in range(101, 132):
        if i == 101:
            global_renames[f'global_{i}_bo'] = 'g_IsM15Timeframe'
        elif i == 102:
            global_renames[f'global_{i}_in'] = 'g_FontSize'
        elif i == 103:
            global_renames[f'global_{i}_in'] = 'g_ObjectCount'
        elif i == 104:
            global_renames[f'global_{i}_bo'] = 'g_IsFirstRun'
        elif i == 105:
            global_renames[f'global_{i}_bo'] = 'g_IsRecoveryMode'
        elif i == 106:
            global_renames[f'global_{i}_in'] = 'g_RecoveryStep'
        elif i == 107:
            global_renames[f'global_{i}_in'] = 'g_RecoveryAttempts'
        elif i == 108:
            global_renames[f'global_{i}_in'] = 'g_LastErrorCode'
        elif i == 109:
            global_renames[f'global_{i}_in'] = 'g_LastErrorTime'
        elif i == 110:
            global_renames[f'global_{i}_st'] = 'g_LastErrorSymbol'
        elif i == 111:
            global_renames[f'global_{i}_st'] = 'g_LastErrorFunction'
        elif i == 112:
            global_renames[f'global_{i}_st'] = 'g_StatusText1'
        elif i == 113:
            global_renames[f'global_{i}_st'] = 'g_StatusText2'
        elif i == 114:
            global_renames[f'global_{i}_in'] = 'g_ColorConstant'
        elif i == 115:
            global_renames[f'global_{i}_in'] = f'g_Reserved{i-114}'
        elif i == 116:
            global_renames[f'global_{i}_in'] = f'g_Reserved{i-114}'
        elif i == 117:
            global_renames[f'global_{i}_st'] = 'g_DrawdownStatus'
        elif i == 118:
            global_renames[f'global_{i}_in'] = f'g_Reserved{i-114}'
        elif i == 119:
            global_renames[f'global_{i}_in'] = f'g_Reserved{i-114}'
        elif i == 120:
            global_renames[f'global_{i}_st'] = f'g_Reserved{i-114}'
        elif i == 121:
            global_renames[f'global_{i}_bo'] = f'g_Reserved{i-114}'
        elif i == 122:
            global_renames[f'global_{i}_do_si6si5si2'] = 'g_PriceGridArray'
        elif i == 123:
            global_renames[f'global_{i}_bo'] = 'g_GridEnabled'
        elif i == 124:
            global_renames[f'global_{i}_st_ko'] = 'g_SymbolListArray'
        elif i == 125:
            # Spread in price units: MarketInfo(symbol,13) * MarketInfo(symbol,11)
            global_renames[f'global_{i}_do'] = 'g_spread_price_delta'
        elif i == 126:
            # Ask price: MarketInfo(symbol,10)
            global_renames[f'global_{i}_do'] = 'g_ask_price'
        elif i == 127:
            # Bid price: MarketInfo(symbol,9)
            global_renames[f'global_{i}_do'] = 'g_bid_price'
        elif i == 128:
            # Point size: MarketInfo(symbol,11)
            global_renames[f'global_{i}_do'] = 'g_point_size'
        elif i == 129:
            # Symbol spread (points): MarketInfo(symbol,13)
            global_renames[f'global_{i}_do'] = 'g_symbol_spread'
        elif i == 130:
            # Price deviation from previous close in pips
            global_renames[f'global_{i}_do'] = 'g_price_deviation_pips'
        elif i == 131:
            # Array used for OnTester equity statistics
            global_renames[f'global_{i}_do_ko'] = 'g_equity_change_array'
    
    # 将全局变量映射添加到主映射
    for old_name, new_name in global_renames.items():
        rename_map[r'\b' + re.escape(old_name) + r'\b'] = new_name
    
    # 结构体成员重命名
    struct_renames = {
        r'\bst_1\b': 'setName',
        r'\bin_2\b': 'magicNumber',
        r'\bdo_3\b': 'martinMultiplier',
        r'\bdo_4\b': 'minProfitPercent',
        r'\bdo_5\b': 'maxDrawdownPercent',
        r'\bdo_6\b': 'riskPercent',
        r'\bdo_7\b': 'tpMultiplier',
        r'\bdo_8\b': 'reserved',
    }
    
    # 添加结构体重命名到主映射
    rename_map.update(struct_renames)
    
    # 应用所有替换
    replaced_count = 0
    for pattern, replacement in rename_map.items():
        matches = re.findall(pattern, content)
        if matches:
            count = len(matches)
            print(f"替换 {pattern} -> {replacement} (找到 {count} 处)")
            content = re.sub(pattern, replacement, content)
            replaced_count += count
    
    # 特殊处理局部变量
    print("\n处理局部变量重命名...")
    
    # 局部变量模式替换
    local_patterns = {
        r'local_(\d+)_in': r'localInt_\1',
        r'local_(\d+)_do': r'localDouble_\1',
        r'local_(\d+)_st': r'localString_\1',
        r'local_(\d+)_bo': r'localBool_\1',
        r'local_(\d+)_lo': r'localLong_\1',
        r'local_(\d+)_co': r'localColor_\1',
        r'local_(\d+)_a_(\d+)': r'localStruct_\1_\2',
        
        r'tmp_(\w+)_(\d+)': r'temp\1_\2',
        r'para_(\d+)_(\w+)': r'param\1_\2',
    }
    
    for pattern, replacement in local_patterns.items():
        content = re.sub(pattern, replacement, content)
    
    # 保存结果，使用与源文件相同的编码（如果是UTF-16，使用UTF-8）
    output_encoding = 'utf-8-sig' if encoding.startswith('utf-16') else encoding
    if encoding == 'utf-8':
        output_encoding = 'utf-8-sig'  # 添加BOM以确保兼容性
    
    try:
        with codecs.open(output_file, 'w', encoding=output_encoding) as f:
            f.write(content)
        print(f"\n重命名完成！")
        print(f"共替换了 {replaced_count} 处标识符")
        print(f"输出文件: {output_file}")
        print(f"输出编码: {output_encoding}")
        print("\n注意: 请手动检查生成的文件，可能需要进一步调整某些特殊情况。")
    except Exception as e:
        print(f"保存文件失败: {e}")

if __name__ == '__main__':
    apply_renames()